#!/usr/bin/env python3
"""
专门处理带FRADIUS的复杂PLOOP - 展示完整的SET2D处理流程
"""

import math
import re
from typing import List, Tuple, Optional
from dataclasses import dataclass

@dataclass
class Vertex:
    """顶点数据结构"""
    x: float
    y: float
    z: float
    fradius: Optional[float] = None
    
    def __str__(self):
        if self.fradius:
            return f"({self.x:.2f}, {self.y:.2f}, {self.z:.2f}, FRAD:{self.fradius:.2f})"
        return f"({self.x:.2f}, {self.y:.2f}, {self.z:.2f})"

def find_fradius_ploop(content: str):
    """找到带有FRADIUS的PLOOP"""
    lines = content.split('\n')
    
    # 找到K717的PLOOP（有3个FRADIUS）
    in_k717 = False
    in_ploop = False
    vertices = []
    height = 0.0
    current_vertex = None
    
    print(f"总行数: {len(lines)}")
    
    for line_num, line in enumerate(lines, 1):
        line = line.strip()
        
        if line.startswith('NEW FRMWORK /1KA-ARCH-P-R-K717'):
            in_k717 = True
            print(f"🔍 第{line_num}行: 找到目标FRMWORK: /1KA-ARCH-P-R-K717")
            
        elif in_k717 and line == 'NEW PLOOP':
            in_ploop = True
            print(f"📐 第{line_num}行: 开始解析PLOOP...")
            
        elif in_k717 and in_ploop and line.startswith('HEIG'):
            height_match = re.search(r'HEIG\s+([\d.-]+)mm', line)
            if height_match:
                height = float(height_match.group(1))
                print(f"   第{line_num}行: 高度: {height}mm")
        
        elif in_k717 and in_ploop and line == 'NEW PAVERT':
            current_vertex = {'x': 0.0, 'y': 0.0, 'z': 0.0, 'fradius': None}
            print(f"   第{line_num}行: 开始新顶点")
        
        elif in_k717 and in_ploop and line.startswith('POS') and current_vertex is not None:
            # 解析位置
            x, y, z = parse_position(line)
            current_vertex.update({'x': x, 'y': y, 'z': z})
            print(f"   第{line_num}行: POS -> ({x:.2f}, {y:.2f}, {z:.2f})")
            
        elif in_k717 and in_ploop and line.startswith('FRAD') and current_vertex is not None:
            # 添加FRADIUS到当前顶点
            frad_match = re.search(r'FRAD\s+([\d.-]+)mm', line)
            if frad_match:
                current_vertex['fradius'] = float(frad_match.group(1))
                print(f"   第{line_num}行: 🔄 添加圆角: {current_vertex['fradius']}mm")
        
        elif in_k717 and in_ploop and line == 'END' and current_vertex is not None:
            # 顶点结束，保存顶点
            vertices.append(current_vertex.copy())
            vertex_count = len(vertices)
            if current_vertex['fradius']:
                print(f"   第{line_num}行: ✅ 保存顶点[{vertex_count-1}]: ({current_vertex['x']:.2f}, {current_vertex['y']:.2f}) FRAD:{current_vertex['fradius']}mm")
            else:
                print(f"   第{line_num}行: ✅ 保存顶点[{vertex_count-1}]: ({current_vertex['x']:.2f}, {current_vertex['y']:.2f})")
            current_vertex = None
        
        elif in_k717 and in_ploop and line.startswith('NEW FRMWORK'):
            # 下一个FRMWORK开始，结束当前PLOOP
            print(f"   第{line_num}行: 遇到下一个FRMWORK，结束解析")
            break
        
        elif in_k717 and in_ploop and line == 'INPUT END':
            # 文件结束
            print(f"   第{line_num}行: 遇到INPUT END，结束解析")
            break
    
    print(f"📊 解析完成: 共找到 {len(vertices)} 个顶点")
    
    # 转换为Vertex对象
    vertex_objects = []
    for i, v in enumerate(vertices):
        vertex_obj = Vertex(v['x'], v['y'], v['z'], v['fradius'])
        vertex_objects.append(vertex_obj)
        if v['fradius']:
            print(f"   顶点[{i}]: {vertex_obj}")
    
    return vertex_objects, height

def parse_position(pos_str: str) -> Tuple[float, float, float]:
    """解析位置字符串"""
    x, y, z = 0.0, 0.0, 0.0
    
    # 解析E/W方向（X轴）
    e_match = re.search(r'E\s+([\d.-]+)mm', pos_str)
    w_match = re.search(r'W\s+([\d.-]+)mm', pos_str)
    if e_match:
        x = float(e_match.group(1))
    elif w_match:
        x = -float(w_match.group(1))
    
    # 解析N/S方向（Y轴）
    n_match = re.search(r'N\s+([\d.-]+)mm', pos_str)
    s_match = re.search(r'S\s+([\d.-]+)mm', pos_str)
    if n_match:
        y = float(n_match.group(1))
    elif s_match:
        y = -float(s_match.group(1))
    
    # 解析U方向（Z轴）
    u_match = re.search(r'U\s+([\d.-]+)mm', pos_str)
    if u_match:
        z = float(u_match.group(1))
    
    return x, y, z

def calculate_fillet_arc_detailed(prev_vertex: Vertex, vertex: Vertex, next_vertex: Vertex) -> List[Vertex]:
    """详细计算内切圆弧顶点 - 展示完整计算过程"""
    print(f"\n🔧 处理圆角顶点: {vertex}")
    print(f"   前一顶点: {prev_vertex}")
    print(f"   后一顶点: {next_vertex}")
    
    if vertex.fradius is None or vertex.fradius <= 0:
        print("   ⚠️ 无圆角半径，跳过处理")
        return [vertex]
    
    # 计算前后边的向量
    v1_x = vertex.x - prev_vertex.x
    v1_y = vertex.y - prev_vertex.y
    v2_x = next_vertex.x - vertex.x  
    v2_y = next_vertex.y - vertex.y
    
    print(f"   📊 边向量计算:")
    print(f"      V1 = ({v1_x:.2f}, {v1_y:.2f})")
    print(f"      V2 = ({v2_x:.2f}, {v2_y:.2f})")
    
    # 标准化向量
    len1 = math.sqrt(v1_x*v1_x + v1_y*v1_y)
    len2 = math.sqrt(v2_x*v2_x + v2_y*v2_y)
    
    print(f"      边长: L1={len1:.2f}mm, L2={len2:.2f}mm")
    
    if len1 < 0.001 or len2 < 0.001:
        print("   ⚠️ 边长太短，跳过处理")
        return [vertex]
    
    v1_x /= len1
    v1_y /= len1
    v2_x /= len2
    v2_y /= len2
    
    print(f"      单位向量: U1=({v1_x:.3f}, {v1_y:.3f}), U2=({v2_x:.3f}, {v2_y:.3f})")
    
    # 计算夹角
    dot_product = v1_x * v2_x + v1_y * v2_y
    dot_product = max(-1.0, min(1.0, dot_product))  # 限制范围
    
    angle = math.acos(abs(dot_product))
    half_angle = angle / 2.0
    
    print(f"      夹角: {math.degrees(angle):.2f}°, 半角: {math.degrees(half_angle):.2f}°")
    
    if half_angle < 0.001:  # 角度太小，跳过圆角
        print("   ⚠️ 角度太小，跳过圆角处理")
        return [vertex]
    
    # 计算到切点的距离
    tan_half = math.tan(half_angle)
    dist_to_tangent = vertex.fradius / tan_half
    
    print(f"      切点距离: {dist_to_tangent:.2f}mm")
    
    # 限制切点距离，防止超出边长
    max_dist1 = len1 * 0.9
    max_dist2 = len2 * 0.9
    original_dist = dist_to_tangent
    dist_to_tangent = min(dist_to_tangent, max_dist1, max_dist2)
    
    if original_dist != dist_to_tangent:
        print(f"      切点距离限制: {original_dist:.2f} → {dist_to_tangent:.2f}mm")
    
    # 计算两个切点
    tangent1_x = vertex.x - v1_x * dist_to_tangent
    tangent1_y = vertex.y - v1_y * dist_to_tangent
    tangent2_x = vertex.x + v2_x * dist_to_tangent
    tangent2_y = vertex.y + v2_y * dist_to_tangent
    
    print(f"      切点1: ({tangent1_x:.2f}, {tangent1_y:.2f})")
    print(f"      切点2: ({tangent2_x:.2f}, {tangent2_y:.2f})")
    
    # 计算圆心
    bisector_x = v1_x + v2_x
    bisector_y = v1_y + v2_y
    bisector_len = math.sqrt(bisector_x*bisector_x + bisector_y*bisector_y)
    
    if bisector_len < 0.001:
        print("   ⚠️ 角平分线计算失败")
        return [vertex]
    
    bisector_x /= bisector_len
    bisector_y /= bisector_len
    
    # 判断凸凹性
    cross_product = v1_x * v2_y - v1_y * v2_x
    radius_sign = 1.0 if cross_product > 0 else -1.0
    
    center_dist = vertex.fradius / math.sin(half_angle)
    center_x = vertex.x + bisector_x * center_dist * radius_sign
    center_y = vertex.y + bisector_y * center_dist * radius_sign
    
    convex_type = "凸角" if cross_product > 0 else "凹角"
    print(f"      角类型: {convex_type}")
    print(f"      圆心: ({center_x:.2f}, {center_y:.2f})")
    print(f"      圆心距离: {center_dist:.2f}mm")
    
    # 生成圆弧顶点
    arc_vertices = []
    
    # 计算圆弧角度
    angle1 = math.atan2(tangent1_y - center_y, tangent1_x - center_x)
    angle2 = math.atan2(tangent2_y - center_y, tangent2_x - center_x)
    
    # 确定扫描方向
    angle_diff = angle2 - angle1
    if abs(angle_diff) > math.pi:
        if angle_diff > 0:
            angle_diff -= 2 * math.pi
        else:
            angle_diff += 2 * math.pi
    
    arc_length = abs(angle_diff) * vertex.fradius
    num_segments = max(2, int(arc_length / 200.0))  # 每200mm一个分段
    
    print(f"      圆弧角度: {math.degrees(abs(angle_diff)):.2f}°")
    print(f"      圆弧长度: {arc_length:.2f}mm")
    print(f"      分段数: {num_segments}")
    
    # 添加第一个切点
    arc_vertices.append(Vertex(tangent1_x, tangent1_y, vertex.z))
    
    # 生成中间圆弧点
    for i in range(1, num_segments):
        t = i / num_segments
        current_angle = angle1 + angle_diff * t
        arc_x = center_x + vertex.fradius * math.cos(current_angle)
        arc_y = center_y + vertex.fradius * math.sin(current_angle)
        arc_vertices.append(Vertex(arc_x, arc_y, vertex.z))
    
    # 添加第二个切点
    arc_vertices.append(Vertex(tangent2_x, tangent2_y, vertex.z))
    
    print(f"      生成圆弧顶点: {len(arc_vertices)} 个")
    for i, av in enumerate(arc_vertices):
        print(f"        [{i}] {av}")
    
    return arc_vertices

def process_complex_ploop(vertices: List[Vertex], height: float):
    """处理复杂的PLOOP"""
    print(f"\n📋 原始PLOOP信息:")
    print(f"   高度: {height}mm")
    print(f"   顶点数: {len(vertices)}")
    
    # 统计圆角信息
    fradius_vertices = [(i, v) for i, v in enumerate(vertices) if v.fradius is not None]
    print(f"   圆角顶点: {len(fradius_vertices)} 个")
    
    for i, v in fradius_vertices:
        print(f"     顶点[{i}]: 半径 {v.fradius}mm")
    
    print(f"\n📐 原始顶点列表:")
    for i, v in enumerate(vertices):
        print(f"  [{i:2d}] {v}")
    
    # 移除重复顶点
    unique_vertices = []
    for i, v in enumerate(vertices):
        if i == 0 or (abs(v.x - vertices[i-1].x) > 0.001 or 
                     abs(v.y - vertices[i-1].y) > 0.001):
            unique_vertices.append(v)
    
    print(f"\n🔄 去重后顶点数: {len(unique_vertices)}")
    
    # 处理圆角
    processed_vertices = []
    n = len(unique_vertices)
    
    # 确保闭合
    if n > 2 and (abs(unique_vertices[0].x - unique_vertices[-1].x) > 0.001 or 
                  abs(unique_vertices[0].y - unique_vertices[-1].y) > 0.001):
        unique_vertices.append(unique_vertices[0])
        n = len(unique_vertices)
    
    print(f"\n🔧 开始圆角处理...")
    
    for i in range(n - 1):  # 跳过最后一个重复点
        current = unique_vertices[i]
        prev_vertex = unique_vertices[i - 1] if i > 0 else unique_vertices[n - 2]
        next_vertex = unique_vertices[i + 1]
        
        # 处理圆角
        arc_vertices = calculate_fillet_arc_detailed(prev_vertex, current, next_vertex)
        processed_vertices.extend(arc_vertices)
    
    print(f"\n✅ 最终Profile结果:")
    print(f"   处理前顶点数: {len(vertices)}")
    print(f"   处理后顶点数: {len(processed_vertices)}")
    
    # 计算边界
    if processed_vertices:
        x_coords = [v.x for v in processed_vertices]
        y_coords = [v.y for v in processed_vertices]
        
        bounds = {
            'min_x': min(x_coords),
            'max_x': max(x_coords),
            'min_y': min(y_coords), 
            'max_y': max(y_coords),
            'width': max(x_coords) - min(x_coords),
            'height': max(y_coords) - min(y_coords)
        }
        
        print(f"\n📏 几何边界信息:")
        print(f"   X范围: {bounds['min_x']:.2f} ~ {bounds['max_x']:.2f} mm (宽度: {bounds['width']:.2f}mm)")
        print(f"   Y范围: {bounds['min_y']:.2f} ~ {bounds['max_y']:.2f} mm (高度: {bounds['height']:.2f}mm)")
    
    print(f"\n📋 最终Profile顶点坐标:")
    for i, v in enumerate(processed_vertices):
        print(f"  [{i:3d}] {v}")
    
    return processed_vertices

def export_for_visualizer(profiles, output_file="ploop_profiles.json"):
    """导出处理后的PLOOP profile数据到JSON文件，供Rust可视化器使用"""
    export_data = {
        "profiles": [],
        "metadata": {
            "total_profiles": len(profiles),
            "processing_date": "2025-06-18",
            "description": "PLOOP cross-section profiles with FRADIUS arc processing"
        }
    }
    
    for ploop_id, profile in profiles.items():
        if profile:
            # 计算边界框
            x_coords = [p[0] for p in profile]
            y_coords = [p[1] for p in profile]
            
            profile_data = {
                "id": ploop_id,
                "vertices": [[float(p[0]), float(p[1])] for p in profile],
                "vertex_count": len(profile),
                "bounds": {
                    "min_x": float(min(x_coords)),
                    "max_x": float(max(x_coords)),
                    "min_y": float(min(y_coords)),
                    "max_y": float(max(y_coords)),
                    "width": float(max(x_coords) - min(x_coords)),
                    "height": float(max(y_coords) - min(y_coords))
                }
            }
            export_data["profiles"].append(profile_data)
    
    with open(output_file, 'w', encoding='utf-8') as f:
        import json
        json.dump(export_data, f, indent=2, ensure_ascii=False)
    
    print(f"\n=== 导出可视化数据 ===")
    print(f"输出文件: {output_file}")
    print(f"导出了 {len(export_data['profiles'])} 个 PLOOP 截面")
    return output_file

def main():
    """主函数"""
    # 读取文件
    with open('717.txt', 'r', encoding='utf-8') as f:
        content = f.read()
    
    print("🚀 开始处理带FRADIUS的复杂PLOOP")
    print("="*80)
    
    # 解析目标PLOOP (只处理一个示例)
    vertices, height = find_fradius_ploop(content)
    
    if not vertices:
        print("❌ 未找到目标PLOOP")
        return
    
    # 处理PLOOP
    processed_vertices = process_complex_ploop(vertices, height)
    
    print("\n" + "="*80)
    print("🎉 PLOOP处理完成！")
    print(f"这就是基于IDA Pro分析的SET2D算法实现的LOOP顶点数据到截面profile的完整转换过程。")

    # 创建简单的导出数据
    all_profiles = {
        "K717_COMPLEX": [(v.x, v.y) for v in processed_vertices]
    }
    
    # 导出供Rust可视化器使用
    export_for_visualizer(all_profiles, "ploop_visualizer/ploop_profiles.json")

if __name__ == "__main__":
    main() 